﻿
#region Using Directives.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using ActiproSoftware.SyntaxEditor;
using S3.WMDSLEditor.Client.Forms;
using S3.WMDSLEditor.Common;

#endregion

namespace S3.WMDSLEditor.Client
{
    public partial class FormWmdslEditor : Form
    {
        #region Fields.

        private XmlDocument _wmdslDocument;
        private readonly string _winName = string.Format("{0} {1}", Application.ProductName, Application.ProductVersion);
        private const string MsgBoxName = "WMDSL Editor Message";
        private string _wmdslFilePath;
        private string _wmdslBackupFilePath;
        private string _viewClassName = string.Empty;
        private ResourceManager _resourceManager;
        private const string StartComment = "<!--";
        private const string EndComment = "-->";
        private Document _viewDoc;
        protected MruStripMenu MruMenu;

        #endregion

        #region Constructor.

        public FormWmdslEditor()
        {
            InitializeComponent();

            MruMenu = new MruStripMenu(recentFileMenuItem, OnMruFile, 16);
        }

        #endregion

        #region Form Evemts.

        private void OnMruFile(int number, String filename)
        {
            if(File.Exists(filename))
            {
                OpenWmdslFile(filename);
            }
            else
            {
                string message = string.Format("The file: {0} can not be opened and will be removed from the Recent list(s)", filename);

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Error);

                MruMenu.RemoveFile(number);

                if (MruMenu.MenuItems.Count == 0)
                    recentFileMenuItem.Enabled = false;
            }
        }

        private void FormEditor_Load(object sender, EventArgs e)
        {
            InitForm();

            string fileList = Properties.Settings.Default.MruFileList;

            if(!string.IsNullOrEmpty(fileList))
            {
                MruMenu.LoadFromString(fileList);
                recentFileMenuItem.Enabled = true;
            }
        }

        //protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        //{
        //    if (keyData == (Keys.T))
        //    {
        //        MessageBox.Show("What the Ctrl+F?"); return true;
        //    }
        //    return base.ProcessCmdKey(ref msg, keyData);
        //} 

        private void FormEditor_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!string.IsNullOrEmpty(_wmdslFilePath))
            {
                if (syntaxEditor.Document.Modified)
                {
                    var r = MessageBox.Show(this, string.Format("There are changes made to the ViewClass, save changes to {0}?",
                        _wmdslFilePath), MsgBoxName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                    if (r == DialogResult.Cancel)
                    {
                        e.Cancel = true;
                    }
                    else if (r == DialogResult.Yes)
                    {
                        if (!SaveWmdslFile())
                        {
                            e.Cancel = true;
                        }
                    }
                }
            }

            // save previously used projects list
            Properties.Settings.Default.MruFileList = MruMenu.SaveToString();
            Properties.Settings.Default.Save();

        }

        private void FormEditor_Activated(object sender, EventArgs e)
        {
            HasClipboardText();
        }

        #endregion

        #region Context Menu Events.

        private void cutCtxMenuItem_Click(object sender, EventArgs e)
        {
            Cut();
        }

        private void copyCtxMenuItem_Click(object sender, EventArgs e)
        {
            Copy();
        }

        private void pasteCtxMenuItem_Click(object sender, EventArgs e)
        {
            Paste();
        }

        private void deleteCtxMenuItem_Click(object sender, EventArgs e)
        {
            Delete();
        }

        private void selectAllCtxMenuItem_Click(object sender, EventArgs e)
        {
            SelectAll();
        }

        private void selectLineCtxMenuItem_Click(object sender, EventArgs e)
        {
            SelectLine();
        }

        #endregion

        #region Toolbar Events.

        private void tsbOpen_Click(object sender, EventArgs e)
        {
            OpenWmdslFile();
        }

        private void tsbSave_Click(object sender, EventArgs e)
        {
            if (syntaxEditor.Document.Modified)
            {
                SaveWmdslFile();
                tsbSave.Enabled = false;
                fileSaveWMDSLMenuItem.Enabled = false;
            }
        }

        private void tsbClose_Click(object sender, EventArgs e)
        {
            CloseView();
        }

        private void tsbPreview_Click(object sender, EventArgs e)
        {
            PrintPreview();
        }

        private void tsbPrint_Click(object sender, EventArgs e)
        {
            Print();
        }

        private void tsbUndo_Click(object sender, EventArgs e)
        {
            Undo();
        }

        private void tsbRedo_Click(object sender, EventArgs e)
        {
            Redo();
        }

        private void tsbCut_Click(object sender, EventArgs e)
        {
            Cut();
        }

        private void tsbCopy_Click(object sender, EventArgs e)
        {
            Copy();
        }

        private void tsbPaste_Click(object sender, EventArgs e)
        {
            Paste();
        }

        private void tsbIncreaseIndendt_Click(object sender, EventArgs e)
        {
            IncreaseIndent();
        }

        private void tsbDecreaseLineIndent_Click(object sender, EventArgs e)
        {
            DecreaseIndent();
        }

        private void tsbCommentSelection_Click(object sender, EventArgs e)
        {
            CommentSelection();
        }

        private void tsbUncommentSelection_Click(object sender, EventArgs e)
        {
            UncommentSelection();
        }

        private void tsbToggleBookmark_Click(object sender, EventArgs e)
        {
            ToggleBookmark();
        }

        private void tsbPreviousBookmark_Click(object sender, EventArgs e)
        {
            GoToPreviousBookmark();
        }

        private void tsbNextBookmark_Click(object sender, EventArgs e)
        {
            GoToNextBookmark();
        }

        private void tsbClearBookmarks_Click(object sender, EventArgs e)
        {
            ClearBookmarks();
        }

        #endregion

        #region File Menu Events.

        private void fileOpenWMDSLMenuItem_Click(object sender, EventArgs e)
        {
            OpenWmdslFile();
        }

        private void fileSaveWMDSLMenuItem_Click(object sender, EventArgs e)
        {
            if (syntaxEditor.Document.Modified)
            {
                SaveWmdslFile();
                tsbSave.Enabled = false;
                fileSaveWMDSLMenuItem.Enabled = false;
            }
        }

        private void fileSaveWMDSLAsMenuItem_Click(object sender, EventArgs e)
        {
            SaveWmdslFileAs();
        }

        private void fileCloseWMDSLMenuItem_Click(object sender, EventArgs e)
        {
            CloseWmdslFile();
        }

        private void fileCloseViewMenuItem_Click(object sender, EventArgs e)
        {
            CloseView();
        }

        private void fileBackupWMDSLMenuItem_Click(object sender, EventArgs e)
        {
            BackupWmdslFile();
        }

        private void editGotoMenuItem_Click(object sender, EventArgs e)
        {
            if (syntaxEditor.Document.HasContent)
            {
                FormGotoLine frm = new FormGotoLine(syntaxEditor);

                frm.ShowDialog(this);
            }
        }

        private void filePageSetupMenuItem_Click(object sender, EventArgs e)
        {
            PageSetup();
        }

        private void filePrintPreviewMenuItem_Click(object sender, EventArgs e)
        {
            PrintPreview();
        }

        private void filePrintMenuItem_Click(object sender, EventArgs e)
        {
            Print();
        }

        private void filePrintNowMenuItem_Click(object sender, EventArgs e)
        {
            PrintNow();
        }

        private void fileExitMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        #endregion

        #region Edit Menu Events.

        private void editUndoMenuItem_Click(object sender, EventArgs e)
        {
            Undo();
        }

        private void editRedoMenuItem_Click(object sender, EventArgs e)
        {
            Redo();
        }

        private void editCutMenuItem_Click(object sender, EventArgs e)
        {
            Cut();
        }

        private void editCopyMenuItem_Click(object sender, EventArgs e)
        {
            Copy();
        }

        private void editCutAppendMenuItem_Click(object sender, EventArgs e)
        {
            CutAndAppend();
        }

        private void editCopyAppendMenuItem_Click(object sender, EventArgs e)
        {
            CopyAndAppend();
        }

        private void editClearClipboardMenuItem_Click(object sender, EventArgs e)
        {
            ClearClipboard();
        }

        private void editPasteMenuItem_Click(object sender, EventArgs e)
        {
            Paste();
        }

        private void editDeleteMenuItem_Click(object sender, EventArgs e)
        {
            Delete();
        }

        private void editSselectAllMenuItem_Click_1(object sender, EventArgs e)
        {
            SelectAll();
        }
        
        private void editSelectLineMenuItem_Click_1(object sender, EventArgs e)
        {
            SelectLine();
        }
        
        private void editSelectWordMenuItem_Click(object sender, EventArgs e)
        {
            SelectWord();
        }

        private void editSelectNoneMenuItem_Click_1(object sender, EventArgs e)
        {
            SelectNone();
        }

        private void editToggleMenuItem_Click(object sender, EventArgs e)
        {
            ToggleBookmark();
        }

        private void editEnableBookmarkMenuItem_Click(object sender, EventArgs e)
        {
            EnableBookmark();
        }

        private void editEnableAllBookmarksMenuItem_Click(object sender, EventArgs e)
        {
            EnableAllBookmarks();
        }

        private void editPreviousBookmarkMenuItem_Click(object sender, EventArgs e)
        {
            GoToPreviousBookmark();
        }

        private void editNextBookmarkMenuItem_Click(object sender, EventArgs e)
        {
            GoToNextBookmark();
        }

        private void editClearBookmarksMenuItem_Click(object sender, EventArgs e)
        {
            ClearBookmarks();
        }

        private void editCommentSelectionMenuItem_Click(object sender, EventArgs e)
        {
            CommentSelection();
        }

        private void editUncommentSelectionMenuItem_Click(object sender, EventArgs e)
        {
            UncommentSelection();
        }

        #endregion

        #region Format Menu Events.

        private void formatMakeUppercaseMenuItem_Click(object sender, EventArgs e)
        {
            MakeUppercase();
        }

        private void formatMakeLowercaseMenuItem_Click(object sender, EventArgs e)
        {
            MakeLowercase();
        }

        private void formatCapitalizeMenuItem_Click(object sender, EventArgs e)
        {
            Capitalize();
        }

        private void formatInvertCasingMenuItem_Click(object sender, EventArgs e)
        {
            InvertCaseing();
        }

        private void formatIncreaseLineIndentMenuItem_Click(object sender, EventArgs e)
        {
            IncreaseIndent();
        }

        private void decreaseLineIndentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DecreaseIndent();
        }

        #endregion

        #region View Menu Events.

        private void viewShowSpacesTabsMenuItem_Click(object sender, EventArgs e)
        {
            syntaxEditor.WhitespaceSpacesVisible = syntaxEditor.WhitespaceTabsVisible = !syntaxEditor.WhitespaceSpacesVisible;
            OnSettingsChanged();
        }

        private void viewShowNewLineMenuItem_Click(object sender, EventArgs e)
        {
            syntaxEditor.WhitespaceLineEndsVisible = !syntaxEditor.WhitespaceLineEndsVisible;
            OnSettingsChanged();
        }

        private void viewMarkLineModificationsMenuItem_Click(object sender, EventArgs e)
        {
            syntaxEditor.Document.LineModificationMarkingEnabled = !syntaxEditor.Document.LineModificationMarkingEnabled;
            OnSettingsChanged();
        }

        private void viewhHighlightCurrentLineMenuItem_Click(object sender, EventArgs e)
        {
            syntaxEditor.CurrentLineHighlightingVisible = !syntaxEditor.CurrentLineHighlightingVisible;
            OnSettingsChanged();
        }

        #endregion

        #region Tools Menu Events.

        private void toolsEditAttributesMenuItem_Click(object sender, EventArgs e)
        {
            EditAttributes();
        }

        #endregion

        #region Window Menu Events.

        private void windowSplitVerticalMenuItem_Click_1(object sender, EventArgs e)
        {
            syntaxEditor.HasHorizontalSplit = false;
            syntaxEditor.HasVerticalSplit = true;
        }

        private void windowSplitHorizontalMenuItem_Click(object sender, EventArgs e)
        {
            syntaxEditor.HasHorizontalSplit = true;
            syntaxEditor.HasVerticalSplit = false;
        }

        private void windowSplitFourwayMenuItem_Click(object sender, EventArgs e)
        {
            syntaxEditor.HasHorizontalSplit = true;
            syntaxEditor.HasVerticalSplit = true;
        }

        private void windowNoSplitMenuItem_Click(object sender, EventArgs e)
        {
            syntaxEditor.HasHorizontalSplit = false;
            syntaxEditor.HasVerticalSplit = false;
        }

        #endregion

        #region Help Menu Events.

        private void helpAboutMenuItem_Click(object sender, EventArgs e)
        {
            ShowAbout();
        }

        #endregion

        #region TreeView Events.

        private void tvwViews_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Text == "View Classes")
                return;

            if (syntaxEditor.Document.Modified)
            {
                var closeView = MessageBox.Show(this, string.Format("There are changes made to the View, save changes to {0}?\n\n",
                    _wmdslFilePath), MsgBoxName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                if (closeView == DialogResult.Yes)
                {
                    if (SaveWmdslFile())
                    {
                        syntaxEditor.Document.Modified = false;
                    }
                }
                else if (closeView == DialogResult.No)
                {
                    syntaxEditor.Document.Modified = false;
                }
                else
                {
                    return;
                }
            }

            string selectedView = e.Node.Text;

            UpdateTreeView(tvwViews, selectedView, _wmdslFilePath);

            tvwViews.Invalidate();

            syntaxEditor.Text = string.Empty;

            if (!string.IsNullOrEmpty(selectedView) || selectedView != "View Classes")
            {
                OpenView(selectedView);
            }
            else
            {
                syntaxEditor.Text = string.Empty;

                syntaxEditor.Refresh();

                _viewClassName = string.Empty;
            }
        }

        private void FillTreeView(List<string> views, string path)
        {
            tvwViews.Nodes.Clear();

            TreeNode rootNode = new TreeNode("View Root");

            rootNode.Name = "nodeRoot";
            

            if(Functions.IsFileReadOnly(path))
            {
                rootNode.ImageIndex = 0;
                rootNode.Text = "View Classes (Write Protected)";
                rootNode.SelectedImageIndex = 0;
            }
            else
            {
                rootNode.ImageIndex = 1;
                rootNode.Text = "View Classes";
                rootNode.SelectedImageIndex = 1;
            }

            foreach (string view in views)
            {
                TreeNode node = new TreeNode(view);
                node.ImageIndex = 2;
                node.SelectedImageIndex = 2;

                rootNode.Nodes.Add(node);
            }

            tvwViews.Nodes.Add(rootNode);

            tvwViews.Nodes[0].ExpandAll();
        }

        #endregion

        #region WMDSL File Methods.

        private void OpenWmdslFile(string path)
        {
            if (!string.IsNullOrEmpty(_wmdslFilePath))
            {
                string message = string.Format("The WMDSL-file:\n\n {0}\n\n is already a open for edit, please close that file and try again!", _wmdslFilePath);

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Warning);

                return;
            }

            SetWaitCursor(true);

            _wmdslFilePath = path;

            if (Functions.OpenWmdslFile(_wmdslFilePath, out _wmdslDocument, out _wmdslBackupFilePath))
            {
                FillTreeView(Functions.GetAllViewNames(_wmdslDocument), _wmdslFilePath);
                    
                fileSystemWatcher.Path = Path.GetDirectoryName(_wmdslFilePath);
                    
                fileSystemWatcher.EnableRaisingEvents = true;

                MruMenu.AddFile(_wmdslFilePath);
            }
            else
            {
                const string message = "The selected WMDSL-file could not be opened for edit!";

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            SetEditorFileInfo(_wmdslFilePath);

            SetWaitCursor(false);
        }

        private void OpenWmdslFile()
        {
            if (!string.IsNullOrEmpty(_wmdslFilePath))
            {
                string message = string.Format("The WMDSL-file:\n\n {0}\n\n is already a open for edit, please close that file and try again!", _wmdslFilePath);

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Warning);

                return;
            }

            openFileDialog.Title = @"Open WMDSL File For Edit";
            openFileDialog.ReadOnlyChecked = false;

            DialogResult open = openFileDialog.ShowDialog(this);

            if (open == DialogResult.OK)
            {
                SetWaitCursor(true);

                _wmdslFilePath = openFileDialog.FileName;

                if (Functions.OpenWmdslFile(_wmdslFilePath, out _wmdslDocument, out _wmdslBackupFilePath))
                {
                    FillTreeView(Functions.GetAllViewNames(_wmdslDocument), _wmdslFilePath);
                    
                    fileSystemWatcher.Path = Path.GetDirectoryName(_wmdslFilePath);
                    
                    fileSystemWatcher.EnableRaisingEvents = true;

                    MruMenu.AddFile(_wmdslFilePath);
                }
                else
                {
                    const string message = "The selected WMDSL-file could not be opened for edit!";

                    MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }

            SetEditorFileInfo(_wmdslFilePath);

            SetWaitCursor(false);
        }

        private void CloseWmdslFile()
        {
            bool isClosed = false;

            if (syntaxEditor.Document.Modified)
            {
                var r = MessageBox.Show(this, string.Format("There are some changes made to the View, would you like to save changes to the file {0}?",
                    _wmdslFilePath), MsgBoxName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                SetWaitCursor(true);

                if (r == DialogResult.Yes)
                {
                    if (SaveWmdslFile())
                    {
                        isClosed = true;
                    }
                }
                else if (r == DialogResult.No)
                {
                    isClosed = true;
                }
            }
            else
            {
                SetWaitCursor(true);
                isClosed = true;
            }

            if(isClosed)
            {
                _wmdslFilePath = string.Empty;

                _wmdslDocument = null;

                ResetEditor();
            }
            
            SetEditorFileInfo(_wmdslFilePath);

            SetWaitCursor(false);
        }

        private bool SaveWmdslFile()
        {
            string errorMsg;

            SetWaitCursor(true);

            if (Functions.SaveWmdslFile(_viewClassName, _wmdslDocument, syntaxEditor.Document.GetText(LineTerminator.CarriageReturnNewline), _wmdslFilePath, out errorMsg))
            {
                syntaxEditor.Document.Modified = false;

                SetWindowNameStatus(false);

                SetSaveStatus(false);

                SetWaitCursor(false);

                return true;
            }

            if (!string.IsNullOrEmpty(errorMsg))
            {
                string message = string.Format("There was a problem saving changes to View in the WMDSL-file [{0}]\n\n{1}", _viewClassName, errorMsg);

                SetWaitCursor(false);

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Error);

                return false;
            }

            if (!string.IsNullOrEmpty(_wmdslFilePath) && syntaxEditor.Document.Modified)
            {
                string message = string.Format("There was a problem saving changes to View in the WMDSL-file [{0}]", _viewClassName);

                SetWaitCursor(false);

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return false;
        }

        private void SaveWmdslFileAs()
        {
            if (string.IsNullOrEmpty(_wmdslFilePath))
            {
                const string message = "There is no WMDSL-file open to save!";

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Warning);

                return;
            }

            saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            saveFileDialog.Title = @"Save WMDSL File As";

            DialogResult save = saveFileDialog.ShowDialog(this);

            if (save == DialogResult.OK)
            {
                SetWaitCursor(true);

                if (Functions.SaveWmdslFileAs(_viewClassName, _wmdslDocument, syntaxEditor.Text, _wmdslFilePath, saveFileDialog.FileName))
                {
                    _wmdslFilePath = saveFileDialog.FileName;

                    MruMenu.AddFile(_wmdslFilePath);

                    syntaxEditor.Document.Modified = false;

                    SetWindowNameStatus(false);

                    tsbSave.Enabled = false;

                    fileSaveWMDSLMenuItem.Enabled = false;                    
                }
                else
                {
                    string message = string.Format("There was a problem saving WMDSL-file to [{0}]", saveFileDialog.FileName);
                    SetWaitCursor(false);
                    MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }

            SetEditorFileInfo(_wmdslFilePath);
            
            SetWaitCursor(false);
        }

        private void BackupWmdslFile()
        {
            if (!string.IsNullOrEmpty(_wmdslFilePath))
            {
                saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                saveFileDialog.Title = @"Backup Original WMDSL File To";

                string fileName = Path.GetFileNameWithoutExtension(_wmdslBackupFilePath);

                string backupDatePart = string.Format("{0}{1:0#}{2:0#}", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);

                string backupTimePart = string.Format("{0:0#}{1:0#}{2:0#}", DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);

                saveFileDialog.FileName = string.Format("{0}_{1}_{2}.wmdsl", fileName, backupDatePart, backupTimePart);

                DialogResult save = saveFileDialog.ShowDialog(this);

                SetWaitCursor(true);

                if (save == DialogResult.OK)
                {
                    if (Functions.BackupWmdslFile(_wmdslBackupFilePath, saveFileDialog.FileName))
                    {
                        string message = string.Format("Created a backup of the original WMDSL-file to:\n\n [{0}]", saveFileDialog.FileName);

                        SetWaitCursor(false);

                        MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    else
                    {
                        string message = string.Format("Could not created a backup of the original WMDSL-file to:\n\n [{0}]", saveFileDialog.FileName);

                        SetWaitCursor(false);

                        MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
            }
        }

        #endregion

        #region WMDSL View Methods.

        private void OpenView(string view)
        {
            SetWaitCursor(true);

            if (Functions.OpenViewDocument(_wmdslDocument, view, out _viewDoc))
            {
                _viewClassName = view;

                WmdslLanguages.LoadLanguageDefinitionFromResource(Language.XML, ref _viewDoc);

                //_viewDoc.Language = WmdslLanguages.CreateScriptXmlToSqlLanguage();

                _viewDoc.Outlining.Mode = OutliningMode.Automatic;

                _viewDoc.LineModificationMarkingEnabled = true;

                _viewDoc.SemanticParsingEnabled = true;

                _viewDoc.LexicalParsingEnabled = true;

                syntaxEditor.Document = _viewDoc;

                syntaxEditor.Document.UndoRedoStateChanged += (UndoRedoStateChanged);

                Text = string.Format("{0} [{1}]", _winName, _viewClassName);

                syntaxEditor.Enabled = true;

                syntaxEditor.Document.Modified = false;

                SetSaveStatus(false);

                SetDocumentInfo(syntaxEditor.Document.Length, syntaxEditor.Document.Lines.Count);

                SetWaitCursor(false);
            }
            else
            {
                const string message = "Could not open the selected View for edit!";

                ResetEditor(); 

                SetWaitCursor(false);

                MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void CloseView()
        {
            bool isClosed = false;

            if (syntaxEditor.Document.Modified && syntaxEditor.Document.HasContent)
            {
                var closeView = MessageBox.Show(this, string.Format("There are changes made to the View, save changes to {0}?\n\n",
                    _wmdslFilePath), MsgBoxName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                SetWaitCursor(true);

                if (closeView == DialogResult.Yes)
                {
                    if (SaveWmdslFile())
                    {
                        isClosed = true;
                    }
                }
                else if (closeView == DialogResult.No)
                {
                    isClosed = true;
                }
            }
            else
            {
                SetWaitCursor(true);
                isClosed = true;
            }

            if(isClosed)
            {
                syntaxEditor.Document.UndoRedoStateChanged -= (UndoRedoStateChanged);

                Text = _winName;

                ResetEditor();

                ResetStatusbar();
            }

            SetWaitCursor(false);
        }

        private void viewShowColumn80GuideMenuItem_Click(object sender, EventArgs e)
        {
            ShowColumn80Guide();
        }

        #endregion

        #region File Menu And Toolbar Methods.

        private void PrintNow()
        {
            if (!syntaxEditor.Document.HasContent)
            {
                return;
            }

            string docName = GetPrintingDocumentName(_viewClassName);
            string date = DateTime.Now.ToShortDateString();
            string time = DateTime.Now.ToShortTimeString();

            syntaxEditor.PrintSettings.PrintDocument.DocumentName = docName;
            syntaxEditor.PrintSettings.DocumentTitle = string.Format("Utskrift av vyn[{0}] {1} {2}", _viewClassName, date, time);
            syntaxEditor.Print(false);
        }

        private void Print()
        {
            if (!syntaxEditor.Document.HasContent)
            {
                return;
            }

            string docName = GetPrintingDocumentName(_viewClassName);

            syntaxEditor.PrintSettings.PrintDocument.DocumentName = docName;

            printDialog.Document = syntaxEditor.PrintSettings.PrintDocument;

            printDialog.AllowSelection = true;

            printDialog.AllowSomePages = true;

            DialogResult print = printDialog.ShowDialog(this);

            if (print == DialogResult.OK)
            {
                string date = DateTime.Now.ToShortDateString();
                string time = DateTime.Now.ToShortTimeString();

                syntaxEditor.PrintSettings.DocumentTitle = string.Format("Utskrift av vyn[{0}] {1} {2}", _viewClassName, date, time);
                syntaxEditor.PrintSettings.PrintDocument.PrinterSettings = printDialog.PrinterSettings;
                syntaxEditor.PrintSettings.PrintDocument.Print();
            }
        }

        private void PrintPreview()
        {
            if (!syntaxEditor.Document.HasContent)
            {
                return;
            }

            string docName = GetPrintingDocumentName(_viewClassName);

            var s = new Size(1200, 900);
            var bitmap = (Bitmap)_resourceManager.GetObject("PrintPreviewHS");

            printPreviewDialog.Size = s;
            printPreviewDialog.StartPosition = FormStartPosition.CenterScreen;
            printPreviewDialog.PrintPreviewControl.Zoom = 1.0;
            printPreviewDialog.Text = String.Format("Preview {0}", docName);

            if (bitmap != null)
            {
                printPreviewDialog.Icon = Icon.FromHandle(bitmap.GetHicon());
            }

            string date = DateTime.Now.ToShortDateString();
            string time = DateTime.Now.ToShortTimeString();

            syntaxEditor.PrintSettings.DocumentTitle = string.Format("Utskrift av vyn[{0}] {1} {2}", _viewClassName, date, time);

            printPreviewDialog.Document = syntaxEditor.PrintSettings.PrintDocument;
            printPreviewDialog.Document.DocumentName = docName;
            printPreviewDialog.ShowDialog(this);
        }

        private void PageSetup()
        {
            syntaxEditor.ShowPageSetupForm(this);
        }

        #endregion

        #region Edit Menu And Toolbar Methods.

        private void Undo()
        {
            syntaxEditor.Document.UndoRedo.Undo();
        }

        private void Redo()
        {
            syntaxEditor.Document.UndoRedo.Redo();
        }

        private void Cut()
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            syntaxEditor.SelectedView.CutToClipboard();
            HasClipboardText();
        }

        private void Copy()
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            syntaxEditor.SelectedView.CopyToClipboard();
            HasClipboardText();
        }

        private void Paste()
        {
            if (syntaxEditor.Enabled)
            {
                syntaxEditor.SelectedView.PasteFromClipboard();
            }
        }

        private void CutAndAppend()
        {
            syntaxEditor.SelectedView.CutAndAppendToClipboard();
        }

        private void CopyAndAppend()
        {
            syntaxEditor.SelectedView.CopyAndAppendToClipboard();
        }

        private void ClearClipboard()
        {
            if (Clipboard.ContainsText(TextDataFormat.UnicodeText) || Clipboard.ContainsText(TextDataFormat.Text))
            {
                Clipboard.Clear();
                HasClipboardText();
            }
        }

        private void Delete()
        {
            syntaxEditor.SelectedView.Delete();
        }

        private void SelectAll()
        {
            syntaxEditor.SelectedView.Selection.SelectAll();
        }

        private void SelectLine()
        {
            syntaxEditor.SelectedView.Selection.MoveToLineStart();
            syntaxEditor.SelectedView.Selection.SelectToLineEnd();
        }

        private void SelectWord()
        {
            syntaxEditor.SelectedView.Selection.SelectWord();
        }

        private void SelectNone()
        {
            int offset = syntaxEditor.SelectedView.Selection.FirstOffset;
            syntaxEditor.SelectedView.Selection.SelectRange(offset, 0);
        }

        private void ToggleBookmark()
        {
            if (syntaxEditor.SelectedView.CurrentDocumentLine.LineIndicators.Contains(BookmarkLineIndicator.DefaultName))
            {
                syntaxEditor.SelectedView.CurrentDocumentLine.LineIndicators.Clear(BookmarkLineIndicator.DefaultName);
            }
            else
            {
                syntaxEditor.Document.LineIndicators.Add(new BookmarkLineIndicator(), syntaxEditor.Caret.DocumentPosition.Line);
            }
        }

        private void EnableBookmark()
        {
            int index = syntaxEditor.SelectedView.CurrentDocumentLine.LineIndicators.IndexOf(BookmarkLineIndicator.DefaultName);

            if (index != -1)
            {
                (syntaxEditor.SelectedView.CurrentDocumentLine.LineIndicators[index]).CanNavigateTo =
                    !(syntaxEditor.SelectedView.CurrentDocumentLine.LineIndicators[index]).CanNavigateTo;

                syntaxEditor.Invalidate();
            }
        }

        private void EnableAllBookmarks()
        {
            DocumentLineCollection lines = syntaxEditor.Document.Lines;

            foreach (DocumentLine line in lines)
            {
                int index = line.LineIndicators.IndexOf(BookmarkLineIndicator.DefaultName);

                if (index != -1 && line.LineIndicators[index].CanNavigateTo == false)
                {
                    line.LineIndicators[index].CanNavigateTo = true;
                }
            }

            syntaxEditor.Invalidate();
        }

        private void GoToPreviousBookmark()
        {
            syntaxEditor.SelectedView.GotoPreviousLineIndicator(BookmarkLineIndicator.DefaultName);
        }

        private void GoToNextBookmark()
        {
            syntaxEditor.SelectedView.GotoNextLineIndicator(BookmarkLineIndicator.DefaultName);
        }

        private void ClearBookmarks()
        {
            const string message = "Are you sure that you want to clear all bookmarks?";

            DialogResult clearBookmarks = MessageBox.Show(this, message, MsgBoxName, MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (clearBookmarks == DialogResult.Yes)
            {
                syntaxEditor.Document.LineIndicators.Clear(BookmarkLineIndicator.DefaultName);
            }
        }

        private void CommentSelection()
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            if (!syntaxEditor.SelectedView.SelectedText.StartsWith(StartComment) && !syntaxEditor.SelectedView.SelectedText.EndsWith(EndComment))
            {
                int startLine = syntaxEditor.SelectedView.Selection.StartDocumentPosition.Line;
                int endLine = syntaxEditor.SelectedView.Selection.EndDocumentPosition.Line;
                int selLines = syntaxEditor.SelectedView.Selection.DocumentPositionRange.Lines;
                int startSelection = startLine;

                if (startLine > endLine)
                    startSelection = endLine;

                int endSelection = startSelection + selLines - 1;

                int ws = syntaxEditor.Document.Lines[startSelection].StartOffset + syntaxEditor.Document.Lines[startSelection].IndentAmount;

                TextRange range = new TextRange(ws, syntaxEditor.Document.Lines[endSelection].EndOffset);

                syntaxEditor.SelectedView.Selection.SelectRange(range);

                syntaxEditor.SelectedView.InsertSurroundingText(DocumentModificationType.Typing, StartComment, EndComment);

                range = new TextRange(syntaxEditor.Document.Lines[startSelection].StartOffset, syntaxEditor.Document.Lines[endSelection].EndOffset);

                syntaxEditor.SelectedView.Selection.SelectRange(range);
            }
        }

        private void UncommentSelection()
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            string startText = syntaxEditor.SelectedView.SelectedText.Trim();

            if (startText.StartsWith(StartComment) && syntaxEditor.SelectedView.SelectedText.EndsWith(EndComment))
            {
                int startLine = syntaxEditor.SelectedView.Selection.StartDocumentPosition.Line;
                int endLine = syntaxEditor.SelectedView.Selection.EndDocumentPosition.Line;
                int selLines = syntaxEditor.SelectedView.Selection.DocumentPositionRange.Lines;

                int startSelection = startLine;

                if (startLine > endLine)
                    startSelection = endLine;

                int endSelection = startSelection + selLines - 1;

                StringBuilder sb = new StringBuilder(syntaxEditor.SelectedView.SelectedText);

                sb.Replace(StartComment, string.Empty);

                sb.Replace(EndComment, string.Empty);

                syntaxEditor.SelectedView.SelectedText = sb.ToString();

                TextRange range = new TextRange(syntaxEditor.Document.Lines[startSelection].StartOffset, syntaxEditor.Document.Lines[endSelection].EndOffset);

                syntaxEditor.SelectedView.Selection.SelectRange(range);
            }
        }

        #endregion

        #region Format Menu And Toolbar Methods.

        private void MakeUppercase()
        {
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Upper);
        }

        private void MakeLowercase()
        {
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Lower);
        }

        private void Capitalize()
        {
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Lower);
            syntaxEditor.SelectedView.ChangeCharacterCasing(CharacterCasing.Normal);
        }

        private void InvertCaseing()
        {
            syntaxEditor.SelectedView.SelectedText = Functions.InvertCasing(syntaxEditor.SelectedView.SelectedText);
        }

        private void IncreaseIndent()
        {
            syntaxEditor.SelectedView.Indent();
        }

        private void DecreaseIndent()
        {
            syntaxEditor.SelectedView.Outdent();
        }

        #endregion

        #region View Menu And Toolbar Methods.

        private void ShowColumn80Guide()
        {
            syntaxEditor.ColumnGuides.Clear();
            if (!viewShowColumn80GuideMenuItem.Checked)
            {
                syntaxEditor.ColumnGuides.Add(new ColumnGuide(ColumnGuideValueType.Column, 80, SystemColors.ControlDark));
            }

            OnSettingsChanged();

            syntaxEditor.Invalidate();
        }

        private void OnSettingsChanged()
        {
            viewShowSpacesTabsMenuItem.Checked = syntaxEditor.WhitespaceSpacesVisible;
            viewShowNewLineMenuItem.Checked = syntaxEditor.WhitespaceLineEndsVisible;
            viewMarkLineModificationsMenuItem.Checked = syntaxEditor.Document.LineModificationMarkingEnabled;
            viewhHighlightCurrentLineMenuItem.Checked = syntaxEditor.CurrentLineHighlightingVisible;
            viewShowColumn80GuideMenuItem.Checked = !viewShowColumn80GuideMenuItem.Checked;
            //menuBracketMatchingStyle.Checked = _editorSettings.BracketMatchingStyle == BracketMatchingStyle.After;
            //menuEnableVirtualSpace.Checked = _editorSettings.AllowCaretBeyondEOL;
            //menuShowLineNumbers.Checked = _editorSettings.ShowLineNumbers;
        }

        #endregion

        #region Tools Menu And Toolbar Methods.

        private void EditAttributes()
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            XmlDocument doc = new XmlDocument();

            doc.LoadXml(syntaxEditor.Text);

            FormEditAttribute frm = new FormEditAttribute(doc);

            DialogResult dialogResult = frm.ShowDialog(this);

            if (dialogResult == DialogResult.OK)
            {
                XmlDocument xdoc = frm.GetXmlDocument;

                string xml = Functions.FormatXml(xdoc.OuterXml);

                syntaxEditor.Document.Text = "";

                syntaxEditor.Text = xml;
            }
        }

        #endregion

        #region Help Menu And Toolbar Methods.

        private void ShowAbout()
        {
            FrmAbout frm = new FrmAbout();

            frm.ShowDialog(this);
        }

        #endregion

        #region Event Implementation.

        private void OnChangeAttributesEvent(object sender, FileSystemEventArgs e)
        {
            if(Functions.IsFileReadOnly(_wmdslFilePath))
            {
                tvwViews.Nodes[0].ImageIndex = 0;
                tvwViews.Nodes[0].Text = @"View Classes (WMDSL-file is Write Protected)";
                tvwViews.Nodes[0].SelectedImageIndex = 0;
            }
            else
            {
                tvwViews.Nodes[0].ImageIndex = 1;
                tvwViews.Nodes[0].Text = @"View Classes";
                tvwViews.Nodes[0].SelectedImageIndex = 1;
            }

            tvwViews.Refresh();
        }

        private void OnOverwriteModeChanged(object sender, EventArgs e)
        {
            SetWriteType();
        }

        private void UndoRedoStateChanged(object sender, UndoRedoStateChangedEventArgs e)
        {
            SetUndoRedoStatus(e.Document.UndoRedo.CanUndo, e.Document.UndoRedo.CanRedo);
        }

        private void syntaxEditor_DocumentTextChanged(object sender, DocumentModificationEventArgs e)
        {
            syntaxEditor.Document.Modified = true;

            SetDocumentInfo(syntaxEditor.Document.Length, syntaxEditor.Document.Lines.Count);

            SetSaveStatus(syntaxEditor.Document.Modified);
        }

        private void syntaxEditor_DocumentModifiedChanged(object sender, EventArgs e)
        {
            SetWindowNameStatus(syntaxEditor.Document.Modified);
        }

        private void syntaxEditor_SelectionChanged(object sender, SelectionEventArgs e)
        {
            DocumentPosition pos =  syntaxEditor.Caret.DisplayDocumentPosition;

            int position = syntaxEditor.Caret.Offset;

            SetPositionInfo(pos.Line, pos.Character, position);

            SetSelectionInfo(syntaxEditor.SelectedView.Selection.Length);
        }

        #endregion

        #region Helper Methods.

        private void InitForm()
        {
            _resourceManager = new ResourceManager("S3.WMDSLEditor.Client.Properties.Resources", GetType().Assembly);

            fileSystemWatcher.Changed += (OnChangeAttributesEvent);
            syntaxEditor.OverwriteModeChanged += (OnOverwriteModeChanged);

            syntaxEditor.Document.LineModificationMarkingEnabled = true;
            viewMarkLineModificationsMenuItem.Checked = true;

            syntaxEditor.Font = new Font("Consolas", 10);
            syntaxEditor.LineNumberMarginFont = new Font("Consolas", 10);
            syntaxEditor.PrintSettings.PrintDocument.DefaultPageSettings.Landscape = true;

            SetWriteType();

            HasClipboardText();

            Text = _winName;

            fileSystemWatcher.EnableRaisingEvents = false;
            fileSystemWatcher.NotifyFilter = NotifyFilters.Attributes;
            fileSystemWatcher.Filter = "*.wmdsl";
        }

        private static void SetWaitCursor(bool isWaitCursor)
        {
            if(isWaitCursor)
                Cursor.Current = Cursors.WaitCursor;
            else
                Cursor.Current = Cursors.Default;
        }

        private void SetWriteType()
        {
            if(syntaxEditor.OverwriteMode)
            {
                statusLabelMode.Text = "OVR";
            }
            else
            {
                statusLabelMode.Text = "INS";
            }
        }

        private void SetWindowNameStatus(bool isModified)
        {
            if (!syntaxEditor.Document.HasContent)
                return;

            if (isModified)
            {
                if (!Text.EndsWith("*"))
                    Text += @" *";
            }
            else
            {
                if (Text.EndsWith("*"))
                    Text = Text.Substring(0, Text.Length - 2);
            }
        }

        private static string GetPrintingDocumentName(string viewName)
        {
            string docName;

            if (string.IsNullOrEmpty(viewName))
            {
                docName = "WMBof View No Name";
            }
            else
            {
                docName = string.Format("WMBof View {0}", viewName);
            }

            return docName;
        }

        private static void UpdateRecursive(TreeNode treeNode, string view, string path)
        {
            bool isReadOnly = Functions.IsFileReadOnly(path);

            foreach (TreeNode tn in treeNode.Nodes)
            {
                if (tn.Text == "Views")
                {
                    if(isReadOnly)
                    {
                        tn.ImageIndex = 1;
                        tn.SelectedImageIndex = 1;
                    }
                    else
                    {
                        tn.ImageIndex = 0;
                        tn.SelectedImageIndex = 0;
                    }
                }
                else if (tn.Text == view)
                {
                    tn.ImageIndex = 3;
                    tn.SelectedImageIndex = 3;
                }
                else
                {
                    tn.ImageIndex = 2;
                    tn.SelectedImageIndex = 2;
                }

                UpdateRecursive(tn, view, path);
            }
        }

        private void UpdateTreeView(TreeView treeView, string view, string path)
        {
            TreeNodeCollection nodes = treeView.Nodes;

            foreach (TreeNode node in nodes)
            {
                UpdateRecursive(node, view, path);
            }
        }

        private void HasClipboardText()
        {
            if (Clipboard.ContainsText(TextDataFormat.UnicodeText) || Clipboard.ContainsText(TextDataFormat.Text))
            {
                tsbPaste.Enabled = true;
                editPasteMenuItem.Enabled = true;
                editCopyAppendMenuItem.Enabled = true;
                editCutAppendMenuItem.Enabled = true;
                editClearClipboardMenuItem.Enabled = true;
                pasteCtxMenuItem.Enabled = true;
            }
            else
            {
                tsbPaste.Enabled = false;
                editPasteMenuItem.Enabled = false;
                editCopyAppendMenuItem.Enabled = false;
                editCutAppendMenuItem.Enabled = false;
                editClearClipboardMenuItem.Enabled = false;
                pasteCtxMenuItem.Enabled = false;
            }
        }

        private void SetEditorFileInfo(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                statusLabelPath.Text = @"No WMDSL-file open for edit";
                statusLabelEncoding.Text = "Encoding :";
            }
            else
            {
                statusLabelPath.Text = text;
                statusLabelEncoding.Text = string.Format("Encoding : {0}", Encoding.UTF8.EncodingName);
            }
        }

        private void ResetStatusbar()
        {
            statusLabelLength.Text = "Length : ";
            statusLabelLines.Text = "Lines : ";
            statusLabelLine.Text = "Ln : ";
            statusLabelCol.Text = "Col : ";
            statusLabelPos.Text = "Pos : ";
            statusLabelSel.Text = "Sel : ";
        }

        private void SetDocumentInfo(int length, int lines)
        {
            statusLabelLength.Text = string.Format("Length : {0:# ###}", length);
            statusLabelLines.Text = string.Format("Lines : {0:# ###}", lines);
        }

        private void SetPositionInfo(int line, int col, int pos)
        {
            statusLabelLine.Text = string.Format("Ln : {0:# ###}", line);
            statusLabelCol.Text = string.Format("Col : {0:# ###}", col);
            statusLabelPos.Text = string.Format("Pos : {0:# ###}", pos);
        }

        private void SetSelectionInfo(int selection)
        {
            statusLabelSel.Text = string.Format("Sel : {0:# ###}", selection);
        }

        private void SetSaveStatus(bool canSave)
        {
            tsbSave.Enabled = canSave;
            fileSaveWMDSLMenuItem.Enabled = canSave;
        }

        private void SetUndoRedoStatus(bool undo, bool redo)
        {
            editUndoMenuItem.Enabled = undo;
            editRedoMenuItem.Enabled = redo;

            tsbUndo.Enabled = undo;
            tsbRedo.Enabled = redo;
        }

        private void ResetEditor()
        {
            syntaxEditor.Text = string.Empty;
            
            syntaxEditor.Refresh();

            syntaxEditor.Enabled = false;

            syntaxEditor.Document.Modified = false;

            _viewClassName = string.Empty;
            
            if (string.IsNullOrEmpty(_wmdslFilePath))
            {
                tvwViews.Nodes.Clear();
            }
            else
            {
                UpdateTreeView(tvwViews, string.Empty, string.Empty);
            }

            SetSaveStatus(false);

            SetUndoRedoStatus(false, false);
            
            SetWindowNameStatus(false);
        }

        #endregion        

        private void formatConvertTabsToSpacesMenuItem_Click(object sender, EventArgs e)
        {
            ConvertTabsToSpaces();
        }

        private void formatConvertSpacesToTabsMenuItem_Click(object sender, EventArgs e)
        {
            ConvertSpacesToTabs();
        }

        private void formatTabifySelectedLinesMenuItem_Click(object sender, EventArgs e)
        {
            TabifySelection();
        }

        private void formatUntabifySelectedLinesMenuItem_Click(object sender, EventArgs e)
        {
            UntabifySelection();
        }

        private void formatTrimTrailingWhitespaceMenuItem_Click(object sender, EventArgs e)
        {
            TrimTrailingWhitespace();
        }

        private void ConvertTabsToSpaces()
        {
            syntaxEditor.SelectedView.ConvertTabsToSpaces();
        }

        private void ConvertSpacesToTabs()
        {
            syntaxEditor.SelectedView.ConvertSpacesToTabs();
        }

        private void TabifySelection()
        {
            syntaxEditor.SelectedView.TabifySelectedLines();
        }

        private void UntabifySelection()
        {
            syntaxEditor.SelectedView.UntabifySelectedLines();
        }

        private void TrimTrailingWhitespace()
        {
            syntaxEditor.SelectedView.TrimTrailingWhitespace();
        }

        private void fileNewViewMenuItem_Click(object sender, EventArgs e)
        {
            NewView();
        }

        private bool NewView()
        {
            if(_wmdslDocument == null)
                return false;

            FormNewView frm = new FormNewView(Functions.GetAllViewNames(_wmdslDocument));

            DialogResult dialogResult = frm.ShowDialog(this);

            if(dialogResult == DialogResult.OK)
            {
                return true;
            }

            return false;
        }
    }
}
